﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="GenericRepository.cs" company="">
//   Copyright (c) 2010/2011 All Right Reserved
// </copyright>
// <summary>
//   Contains GenericRepository class declaration.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace iBuproModel.Repositories.Classes
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;

    using iBuproModel.Repositories.Interfaces;
    using EntityFrameworkExtensions;

    /// <summary>
    /// Generic repository that implements all usual methods.
    /// </summary>
    /// <typeparam name="T">
    /// Entity that the repository is for.
    /// </typeparam>
    public class GenericRepository<T> : IGenericRepository<T> where T : class
    {

        protected Entities context;
        protected IRepositoryService repositoryService;

        public GenericRepository()
        {
            this.context = ContextService.GetInstance;
            this.repositoryService = new RepositoryService();
        }

        public IQueryable<T> GetAll()
        {
            return context.CreateObjectSet<T>().OfTypeOnly<T>();
        }

        public T GetSingle(Expression<Func<T, bool>> filter)
        {
            return this.context.CreateObjectSet<T>().OfTypeOnly<T>().SingleOrDefault<T>(filter);
        }

        public T First(Expression<Func<T, bool>> filter)
        {
            return this.context.CreateObjectSet<T>().OfTypeOnly<T>().FirstOrDefault<T>(filter);
        }

        public void Delete(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            this.context.DeleteObject(entity);
        }

        public void Delete(Expression<Func<T, bool>> filter)
        {
            IEnumerable<T> records = from x in this.context.CreateObjectSet<T>().Where<T>(filter) select x;

            foreach (T record in records)
            {
                this.context.DeleteObject(record);
            }
        }

        public void Add(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            this.context.CreateObjectSet<T>().AddObject(entity);
        }

        public void SaveChanges()
        {
            this.context.SaveChanges();
        }


        public IQueryable<T> GetAll(Expression<Func<T, bool>> filter)
        {

            return context.CreateObjectSet<T>().OfTypeOnly<T>().Where<T>(filter);
        }

        public void Update(T entity)
        {
            var objectSet = context.CreateObjectSet<T>();
            // Fully Qualified Entity Name
            var fqen = string.Format("{0}.{1}", objectSet.EntitySet.EntityContainer, objectSet.EntitySet.Name);
            this.context.ApplyCurrentValues(fqen, entity);
        }



        public void DetachObject(object obj)
        {
            context.Detach(obj);
        }


    }
}
